package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.mapper.RoleResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.ThreadLocalUtil;
import com.zzyl.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private RoleResourceMapper roleResourceMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 根据用户id查询对应的资源数据
     *
     * @return
     */
    @Override
    public List<MenuVo> getMyMenus() {
        Long userId = ThreadLocalUtil.get();
        //查询数据
        List<MenuVo> menuVoList = resourceMapper.selectMenuByUserId(userId);
        //构建 parentNo -> List<MenuVo> 的映射
        Map<String, List<MenuVo>> parentMap = menuVoList.stream().collect(Collectors.groupingBy(MenuVo::getParentResourceNo));
        //递归构建我的菜单信息
        buildTree(menuVoList, parentMap);
        return parentMap.get(SuperConstant.ROOT_RESOURCE_PARENT_ID);
    }

    @Override
    public TreeVo getResourceTree() {
        Long id = ThreadLocalUtil.get();

        String redisKey = "zzyl:resource:tree:vo";

        String redisData = stringRedisTemplate.opsForValue().get(redisKey);

        if (StrUtil.isNotEmpty(redisData)) {
            return JSON.parseObject(redisData, TreeVo.class);
        }

        ResourceDto resourceDto = ResourceDto.builder().resourceType(SuperConstant.MENU).dataState(SuperConstant.DATA_STATE_0).build();
        /*需要一个resourceDto对象调用selectList查找符合条件的集合*/

        List<Resource> resources = resourceMapper.selectList(resourceDto);

        Resource resourceRoot = CollUtil.findOneByField(resources, "resourceNo", SuperConstant.ROOT_RESOURCE_PARENT_ID);

        //3. 构建TreeItemVo对象（树形结构）
        TreeItemVo treeItemVo = TreeItembuild(resources, resourceRoot);

        //4. 创建Vo，返回
        TreeVo treeVo = TreeVo.builder()
                .items(List.of(treeItemVo))
                .build();

        stringRedisTemplate.opsForValue().set(redisKey, JSON.toJSONString(treeVo));

        return treeVo;
    }


    private TreeItemVo TreeItembuild(List<Resource> resources, Resource resource_no) {

        /*构建子树*/
        TreeItemVo treeItemVo = TreeItemVo.builder().id(resource_no.getResourceNo()).label(resource_no.getResourceName()).build();
        /*找到根节点的子节点*/
        Collection<Resource> resourceCollection = CollUtil.filterNew(resources, resource -> StrUtil.equals(resource.getParentResourceNo(), resource_no.getResourceNo()));

        /*判断存不存在子节点*/
        if (CollUtil.isEmpty(resourceCollection)) {
            return treeItemVo;
        }

        /*把Collection<Resource>集合变成List<TreeItemVo>,并且调用递归方法*/
        List<TreeItemVo> collect = resourceCollection.stream().map(res -> TreeItembuild(resources, res)).collect(Collectors.toList());
        /*放入子树*/
        treeItemVo.setChildren(collect);
        return treeItemVo;
    }


    @Override
    public List<ResourceVo> findResourceList(ResourceDto resourceDto) {

        List<Resource> resources = resourceMapper.selectList(resourceDto);

        List<ResourceVo> resourceVos = BeanUtil.copyToList(resources, ResourceVo.class);

        return resourceVos;
    }

    @Override
    public void createResource(ResourceDto resourceDto) {

        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        /*设置资源编号*/

        String resourceNo = createResourceNo(resource, resourceMapper.selectByResourceNo(resourceDto.getParentResourceNo()));

        resource.setResourceNo(resourceNo);

        resource.setDataState(resourceMapper.selectByResourceNo(resourceDto.getParentResourceNo()).getDataState());

        resourceMapper.insert(resource);


    }

    @Override
    public void updateResource(ResourceDto resourceDto) {


        resourceMapper.updateByPrimaryKeySelective(BeanUtil.toBean(resourceDto, Resource.class));

    }

    @Override
    public void isEnable(ResourceDto resourceDto) {
        /*如果该节点的父节点是禁用状态那么该节点不可启用*/
        String dataState = resourceMapper.selectByResourceNo(resourceDto.getParentResourceNo()).getDataState();
        if (StrUtil.equals(resourceDto.getDataState(), SuperConstant.DATA_STATE_0)) {
            if (StrUtil.equals(dataState, SuperConstant.DATA_STATE_1)) {
                throw new BaseException(BasicEnum.PARENT_DEPT_DISABLE);
            }
        }
        resourceMapper.updateByResourceNo(resourceDto.getResourceNo(), resourceDto.getDataState());
        String s = NoProcessing.processString(resourceDto.getResourceNo());
        resourceMapper.updateByParentResourceNo(s, resourceDto.getDataState());
    }

    @Override
    public void deleteByResourceNo(Long menuId) {
        /*判断是否有子菜单*/
        if (resourceMapper.hasChildByMenuId(String.valueOf(menuId)) > 0) {
            throw new BaseException(BasicEnum.SYSYTEM_FAIL);
        }
        /*判断是否和角色关联*/
        if (roleResourceMapper.checkMenuExistRole(String.valueOf(menuId)) > 0) {
            throw new BaseException(BasicEnum.SYSYTEM_FAIL);
        }
        /*判断是否是启用状态*/
        if (StrUtil.equals(resourceMapper.selectByResourceNo(String.valueOf(menuId)).getDataState(), SuperConstant.DATA_STATE_0)) {
            throw new BaseException(BasicEnum.SYSYTEM_FAIL);
        }
        resourceMapper.deleteByResourceNo(String.valueOf(menuId));
    }


    /**
     * 创建资源的编号（已提供）
     * 创建资源的编号（已提供）
     * 创建资源的编号（已提供）
     */
    private String createResourceNo(Resource resource, Resource parentResource) {
        //判断是否是按钮，如果是按钮，则不限制层级
        if (!StrUtil.equals(resource.getResourceType(), SuperConstant.BUTTON)) {
            if (NoProcessing.processString(parentResource.getResourceNo()).length() / 3 >= 5) {
                //判断资源编号是否大于三级
                //100 001 000 000 000
                //100 001 001 000 000
                //100 001 001 001 000
                //100 001 001 001 001 001
                throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
            }
        }

        //根据父资源编号查询子资源
        ResourceDto dto = ResourceDto.builder().parentResourceNo(parentResource.getResourceNo()).build();
        List<Resource> resources = resourceMapper.selectList(dto);
        if (ObjectUtil.isEmpty(resources)) {
            //无下属节点，创建新的节点编号  100 001 001 001 000--->100 001 001 001 001
            return NoProcessing.createNo(parentResource.getResourceNo(), false);
        } else {
            //有下属节点，在已有的节点上追加，先获取已有节点的最大值--100001003000000
            Long maxNo = resources.stream().map(r -> Long.valueOf(r.getResourceNo())).max(Comparator.comparing(i -> i)).get();
            return NoProcessing.createNo(String.valueOf(maxNo), true);
        }
    }


    /**
     * 递归构建我的菜单信息（已提供）
     */
    private void buildTree(List<MenuVo> menuVoList, Map<String, List<MenuVo>> parentMap) {
        menuVoList.forEach(menuVo -> {
            //补全数据
            menuVo.setMeta(MenuMetaVo.builder().title(menuVo.getName()).build());
            menuVo.setRedirect("/" + menuVo.getName());
            //根据当前资源编号查询子资源
            List<MenuVo> childrenList = parentMap.get(menuVo.getResourceNo());
            if (CollUtil.isNotEmpty(childrenList)) {
                buildTree(childrenList, parentMap);
                menuVo.setChildren(childrenList);
            }
        });
    }
}
